package com.weiyi.weiman.quartz;

import com.alibaba.druid.util.StringUtils;
import com.alibaba.fastjson.JSON;
import com.weiyi.weiman.domain.Const.ComicsConst;
import com.weiyi.weiman.domain.Const.ComicsRankConst;
import com.weiyi.weiman.mapper.comics.ComicsMapper;
import com.weiyi.weiman.service.comics.ComicsService;
import com.weiyi.weiman.utils.RedisUtils;
import comics.Comics;
import comics.ComicsIndex;
import comics.ComicsRank;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.io.*;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @Author zhang
 * @Date 2021/5/17 下午1:02
 * @Description
 * @Version 1.0
 **/
@Component
@Slf4j
public class ComicsRankTask {
    @Autowired
    private RedisUtils redisUtils;
    @Autowired
    private ComicsMapper comicsMapper;

    private final String COMICS_INDEX_LOG_PATH = "comicsIndexStatics";
    private final Double BEFORE_WEIGHT_DECAY = 0.8;
    private final Double INDEX_INCREMENT_WEIGHT = 0.4;
    private final Double TOTAL_WEIGHT_DECAY = 0.6;

    /**
     * 更新人气榜单
     */
    @Scheduled(cron = "0 0 */7 * * ?")
    public void updateIndexRank() throws IOException {
        // 漫画的权值信息，key为comicsId，value为权重
        Map<Long, Double> comicsWeight = new HashMap<>();
        Map<Long, ComicsIndex> comicsIndexMap = new HashMap<>();
        // 获取文件夹中所有的文件，并按创建时间排序
        File path1 = new File(COMICS_INDEX_LOG_PATH);
        File[] logFile = path1.listFiles();
        //根据创建时间对文件进行降序排序
        Arrays.sort(logFile, new Comparator<File>() {
            @Override
            public int compare(File file1, File file2) {
                return (int)(file2.lastModified()-file1.lastModified());
            }
        });
        //判断是否有上次创建的文件以及redis中是否有相关数据
        if (logFile.length >= 1) {
            BufferedReader reader = new BufferedReader(new FileReader(logFile[0]));
            String comicsIndexString = null;
            // 读取redis中这段时间内指数变化信息,并进行转化
            Map<Long, ComicsIndex> comicsChangeMap = new HashMap<>();
            Map<Object, Object> indexChangeMap = redisUtils.hGetAll(ComicsConst.COMICS_INDEX_CHANGE);
            indexChangeMap.forEach((key, value) -> comicsChangeMap.put((Long)key, (ComicsIndex)value));
            // 读取文件中所有漫画信息
            while (!StringUtils.isEmpty(comicsIndexString = reader.readLine())) {
                String[] index = comicsIndexString.split(",");
                // 加入权重信息
                comicsWeight.put(Long.parseLong(index[0]), Double.parseDouble(index[index.length-1]));
                ComicsIndex comicsIndex = new ComicsIndex(index[0], index[1], index[2], index[3], index[4]);
                if (comicsChangeMap.containsKey(index[0])) {
                    ComicsIndex changeIndex = comicsChangeMap.get(index[0]);
                    comicsIndex.setComicsLike(comicsIndex.getComicsLike() + changeIndex.getComicsLike());
                    comicsIndex.setComicsCollect(comicsIndex.getComicsCollect() + changeIndex.getComicsCollect());
                    comicsIndex.setComicsSearch(comicsIndex.getComicsSearch() + changeIndex.getComicsSearch());
                    comicsIndex.setComicsVisitor(comicsIndex.getComicsVisitor() + changeIndex.getComicsVisitor());
                }
                comicsIndexMap.put(Long.parseLong(index[0]), comicsIndex);
            }
            reader.close();
            // 更新所有漫画加权值信息
            comicsWeight.forEach((key, value)->{
                value *= BEFORE_WEIGHT_DECAY;
                if (comicsChangeMap.containsKey(key)) {
                    value += getWeightTotal(comicsChangeMap.get(key)) * INDEX_INCREMENT_WEIGHT;
                }
                value *= TOTAL_WEIGHT_DECAY;
                value = Math.floor(value);
                comicsWeight.put(key, value);
                // 将漫画加权值数据写入数据库中
                redisUtils.zAdd(ComicsRankConst.COMICS_RANK_LIST, key.toString(), value);
            });

            // 清空漫画指数更新信息
            redisUtils.delete(ComicsConst.COMICS_INDEX_CHANGE);
        } else {
            // 获取所有漫画信息
            List<Comics> comicsList = comicsMapper.selectList(null);
            for (int i = 0; i < comicsList.size(); i++) {
                Comics comics = comicsList.get(i);
                // 计算加权值
                Double weight;
                ComicsIndex comicsIndex = new ComicsIndex(comics.getComicsId(), comics.getComicsLike(),
                        comics.getComicsCollect(), comics.getComicsVisitor(), comics.getComicsSearch());
                weight = getWeightTotal(comicsIndex);
                comicsWeight.put(comics.getComicsId(), weight);
                comicsIndexMap.put(comics.getComicsId(), comicsIndex);
            }
        }

        // 将漫画相关数值写入文本中
        SimpleDateFormat tempDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String now = tempDate.format(new Date());
        System.out.println(now);
        String fileName = now + ".csv";
        Path path = Paths.get(COMICS_INDEX_LOG_PATH, fileName);
        BufferedWriter out = new BufferedWriter(new FileWriter(path.toString()));
        comicsIndexMap.forEach((key, value)->{
            StringBuilder comicsIndexString = new StringBuilder();
            comicsIndexString.append(value.getComicsId()).append(",")
                    .append(value.getComicsLike()).append(",")
                    .append(value.getComicsCollect()).append(",")
                    .append(value.getComicsVisitor()).append(",")
                    .append(value.getComicsSearch()).append(",")
                    .append(comicsWeight.get(value.getComicsId()));
            try {
                out.write(comicsIndexString.toString());
                out.write("\n");
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
        out.close();
    }

    private Double getWeightTotal(ComicsIndex comicsIndex) {
        return Double.valueOf(comicsIndex.getComicsLike() * ComicsRankConst.LIKE_RATE +
                comicsIndex.getComicsCollect() * ComicsRankConst.COLLECT_RATE +
                comicsIndex.getComicsVisitor() * ComicsRankConst.VISITOR_RATE +
                comicsIndex.getComicsSearch() * ComicsRankConst.SEARCH_RATE);
    }

}
